package de.gof.ppstool.fertigungsverwaltung;

import java.io.Serializable;
import java.util.List;
import javax.persistence.PersistenceContext;
import javax.persistence.EntityManager;
import org.slf4j.Logger;
import de.gof.ppstool.fertigungsverwaltung.db.Fehlendeteile;
import de.gof.ppstool.fertigungsverwaltung.db.FehlendeteileNotFoundException;
import de.gof.ppstool.fertigungsverwaltung.db.Fertigungsauftrag;
import de.gof.ppstool.fertigungsverwaltung.db.FertigungsauftragNotFoundException;
import de.gof.ppstool.fertigungsverwaltung.db.Fertigungsauftragsposition;
import de.gof.ppstool.fertigungsverwaltung.db.FertigungsauftragspositionDuplikatException;
import de.gof.ppstool.fertigungsverwaltung.db.FertigungsauftragspositionNotFoundException;
import de.gof.ppstool.fertigungsverwaltung.db.IFertigungsverwaltungDAO;
import de.gof.ppstool.lagerverwaltung.db.Teil;
import de.gof.ppstool.lagerverwaltung.db.TeileArtNotFoundException;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service(IFertigungsverwaltung.NAME)
@Transactional
public class Fertigungsverwaltung implements IFertigungsverwaltung,
		Serializable {
	private static final long serialVersionUID = -1673139820882585382L;
	private static final Logger LOGGER = LoggerFactory
			.getLogger(Fertigungsverwaltung.class);
	private static final boolean DEBUG = LOGGER.isDebugEnabled();
	@SuppressWarnings("unused")
	@PersistenceContext
	private EntityManager em;
	@Autowired
	private IFertigungsverwaltungDAO dao;

	public Fertigungsverwaltung() {
		super();
	}

	/**
	 * { @inheritDoc}
	 */
	@Transactional
	@Override
	public Fertigungsauftrag erstelleFertigungsauftrag(
			Fertigungsauftrag fertigungsauftrag) {
		if (DEBUG)
			LOGGER.debug("erstelleFertigungsauftrag " + fertigungsauftrag);

		dao.erstelleFertigungsauftrag(fertigungsauftrag);
		return fertigungsauftrag;
	}

	/**
	 * { @inheritDoc}
	 */
	@Transactional
	@Override
	public Fertigungsauftrag aendereFertigungsauftrag(
			Fertigungsauftrag fertigungsauftrag) {
		if (fertigungsauftrag == null) {
			return null;
		}

		fertigungsauftrag = dao.aendereFertigungsauftrag(fertigungsauftrag);
		return fertigungsauftrag;
	}

	/**
	 * { @inheritDoc}
	 */
	@Transactional
	@Override
	public Fertigungsauftragsposition aendereFertigungsauftragsposition(
			Fertigungsauftragsposition fertigungsauftragsposition) {
		if (fertigungsauftragsposition == null) {
			return null;
		}

		fertigungsauftragsposition = dao
				.aendereFertigungsauftragsposition(fertigungsauftragsposition);
		return fertigungsauftragsposition;
	}

	/**
	 * { @inheritDoc}
	 * @throws FertigungsauftragspositionDuplikatException  
	 * @throws FertigungsauftragNotFoundException  
	 */
	@Transactional(rollbackFor = {
			FertigungsauftragspositionDuplikatException.class,
			FertigungsauftragNotFoundException.class })
	@Override
	public Fertigungsauftragsposition erstelleFertigungsauftragsposition(
			Fertigungsauftragsposition fertigungsauftragsposition)
			throws FertigungsauftragspositionDuplikatException,
			FertigungsauftragNotFoundException {
		Fertigungsauftrag fertigungsauftrag = fertigungsauftragsposition
				.getFertigungsauftrag();
		final Long fertigungsauftragId = fertigungsauftrag
				.getFertigungsauftragId();
		try {
			fertigungsauftrag = dao
					.findeFertigungsauftragNachId(fertigungsauftragId);
		} catch (FertigungsauftragNotFoundException e) {
			System.err.println("Fertigungsauftrag nicht mit Id "
					+ fertigungsauftragId
					+ " gefunden!!!! (erstelleFertigungsauftragsPosition())");
			return fertigungsauftragsposition;
			//FIXME			
		}

		final List<Fertigungsauftragsposition> fertigungsauftragspositionen = fertigungsauftrag
				.getFertigungsauftragspositionen();
		// dupe check
		if (fertigungsauftragspositionen != null) {
			for (Fertigungsauftragsposition f : fertigungsauftragspositionen) {
				if (f == fertigungsauftragsposition)
					continue;

				if (!fertigungsauftragsposition.equals(f))
					continue;

				fertigungsauftragspositionen.remove(fertigungsauftragsposition);
				throw new FertigungsauftragspositionDuplikatException(
						fertigungsauftragId);
			}
		}

		fertigungsauftragsposition = dao
				.erstelleFertigungsauftragsposition(fertigungsauftragsposition);
		return fertigungsauftragsposition;
	}

	/**
	 * { @inheritDoc}
	 */
	@Transactional(readOnly = true)
	@Override
	public List<Fertigungsauftrag> findeAlleFertigungsauftraege()
			throws FertigungsauftragNotFoundException {
		List<Fertigungsauftrag> fertigungsauftraege = null;
		try {
			fertigungsauftraege = dao.findeAlleFertigungsauftraege();
		} catch (FertigungsauftragNotFoundException e) {
			throw e;
		}

		return fertigungsauftraege;
	}

	/**
	 * { @inheritDoc}
	 */
	@Transactional(readOnly = true)
	@Override
	public List<Fertigungsauftrag> findeFertigungsauftraegeNachAuftragstag(
			Long auftragstag) throws FertigungsauftragNotFoundException {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * { @inheritDoc}
	 */
	@Transactional(readOnly = true)
	@Override
	public Fertigungsauftrag findeFertigungsauftragNachId(
			Long fertigungsauftragId) throws FertigungsauftragNotFoundException {
		Fertigungsauftrag fertigungsauftrag = null;
		try {
			fertigungsauftrag = dao
					.findeFertigungsauftragNachId(fertigungsauftragId);
		} catch (FertigungsauftragNotFoundException e) {
			throw e;
		}

		return fertigungsauftrag;
	}

	/**
	 * { @inheritDoc}
	 */
	@Transactional(readOnly = true)
	@Override
	public Fertigungsauftragsposition findeFertigungsauftragspositionNachId(
			Long fertigungsauftragspositonId)
			throws FertigungsauftragspositionNotFoundException {
		Fertigungsauftragsposition fertigungsauftragsposition = null;
		try {
			fertigungsauftragsposition = dao
					.findeFertigungsauftragspositionNachId(fertigungsauftragspositonId);
		} catch (FertigungsauftragspositionNotFoundException e) {
			throw e;
		}

		return fertigungsauftragsposition;
	}

	/**
	 * { @inheritDoc}
	 */
	@Transactional(readOnly = true)
	@Override
	public List<Fertigungsauftragsposition> findealleFertigungsauftragspositionen()
			throws FertigungsauftragspositionNotFoundException {
		List<Fertigungsauftragsposition> fertigungsauftragspositionen = null;
		try {
			fertigungsauftragspositionen = dao
					.findealleFertigungsauftragspositionen();
		} catch (FertigungsauftragspositionNotFoundException e) {
			throw e;
		}

		return fertigungsauftragspositionen;
	}

	/**
	 * { @inheritDoc}
	 */
	@Transactional
	@Override
	public void loescheFertigungsauftrag(Fertigungsauftrag fertigungsauftrag)
			throws FertigungsauftragspositionDeleteFertigungsauftragException {
		if (fertigungsauftrag == null) {
			return;
		}

		if (!fertigungsauftrag.getFertigungsauftragspositionen().isEmpty()) {
			final FertigungsauftragspositionDeleteFertigungsauftragException e = new FertigungsauftragspositionDeleteFertigungsauftragException(
					fertigungsauftrag);
			throw e;
		}

		dao.loescheFertigungsauftrag(fertigungsauftrag);
	}

	/**
	 * { @inheritDoc}
	 */
	@Transactional(rollbackFor = {
			FehlendeteileDeleteFertigungsauftragspositionException.class,
			FehlendeteileNotFoundException.class })
	@Override
	public void loescheFertigungsauftragsposition(
			Fertigungsauftragsposition fertigungsauftragsposition)
			throws FehlendeteileDeleteFertigungsauftragspositionException,
			FehlendeteileNotFoundException {
		if (fertigungsauftragsposition == null) {
			return;
		}

		Fehlendeteile fehlendeteile = fertigungsauftragsposition
				.getFehlendeteile();
		if (fehlendeteile != null) {
			final FehlendeteileDeleteFertigungsauftragspositionException e = new FehlendeteileDeleteFertigungsauftragspositionException(
					fertigungsauftragsposition);
			;
			throw e;
		}

		List<Fehlendeteile> fehlendeteileListe = dao.findeAlleFehlendeTeile();
		if (fehlendeteileListe != null) {
			for (Fehlendeteile ft : fehlendeteileListe) {
				Long fertigungsauftragspositionId;
				fertigungsauftragspositionId = ft
						.getFertigungsauftragsposition()
						.getFertigungsauftragspositonId();
				if (fertigungsauftragspositionId == fertigungsauftragsposition
						.getFertigungsauftragspositonId())
					;

				{
					final FehlendeteileDeleteFertigungsauftragspositionException e = new FehlendeteileDeleteFertigungsauftragspositionException(
							fertigungsauftragsposition);
					throw e;
				}
			}
		}

		dao.loescheFertigungsauftragsposition(fertigungsauftragsposition);
	}

	/**
	 * { @inheritDoc}
	 */
	@Transactional(rollbackFor = { FehlendeteileNotFoundException.class })
	@Override
	public Fehlendeteile aendereFehlendeteile(Fehlendeteile fehlendeteile)
			throws FehlendeteileNotFoundException {
		if (fehlendeteile == null) {
			return null;
		}

		fehlendeteile = dao.aendereFehlendeteile(fehlendeteile);
		return fehlendeteile;
	}

	/**
	 * { @inheritDoc}
	 */
	@Transactional(rollbackFor = { FehlendeteileNotFoundException.class })
	@Override
	public Fehlendeteile erstelleFehlendeteile(Fehlendeteile fehlendeteile)
			throws FehlendeteileNotFoundException {
		dao.erstelleFehlendeteile(fehlendeteile);
		return fehlendeteile;
	}

	/**
	 * { @inheritDoc}
	 */
	@Transactional(readOnly = true)
	@Override
	public List<Fehlendeteile> findeAlleFehlendeTeile()
			throws FehlendeteileNotFoundException {
		List<Fehlendeteile> fehlendeteile = null;
		try {
			fehlendeteile = dao.findeAlleFehlendeTeile();
		} catch (FehlendeteileNotFoundException e) {
			throw e;
		}

		return fehlendeteile;
	}

	/**
	 * { @inheritDoc}
	 */
	@Transactional(readOnly = true)
	@Override
	public Fehlendeteile findeFehlendeteileNachId(Long fehlendeteileId)
			throws FehlendeteileNotFoundException {
		Fehlendeteile fehlendeteile = null;
		try {
			fehlendeteile = dao.findeFehlendeteileNachId(fehlendeteileId);
		} catch (FehlendeteileNotFoundException e) {
			throw e;
		}

		return fehlendeteile;
	}

	/**
	 * { @inheritDoc}
	 */
	public void loescheFehlendeteile(Fehlendeteile fehlendeteile) {
		if (fehlendeteile == null) {
			return;
		}

		dao.loescheFehlendeteile(fehlendeteile);
	}

	@Override
	public Fertigungsauftrag findeFertigungsauftragNachBemerkung(
			String bemerkung) throws FertigungsauftragNotFoundException {
		Fertigungsauftrag fertigungsauftrag = null;
		try {
			fertigungsauftrag = dao
					.findeFertigungsauftragNachBemerkung(bemerkung);
		} catch (FertigungsauftragNotFoundException e) {
			throw e;
		}

		return fertigungsauftrag;
	}

	@Override
	public List<Fertigungsauftragsposition> findeFertigungsauftragspositionenNachFertigungsauftrag(
			Long id) {
		List<Fertigungsauftragsposition> fertigungsauftragspositionen = null;
		fertigungsauftragspositionen = dao
				.findeFertigungsauftragspositionenNachFertigungsauftrag(id);
		return fertigungsauftragspositionen;
	}

}
